import AMapLoader from '@amap/amap-jsapi-loader';
import config from './setting';
import "@amap/amap-jsapi-types";
import { ref, Ref } from 'vue';
import { Fn, tryOnMounted, useEventBus } from '@vueuse/core';
import { message } from 'ant-design-vue';

export const createAMap = () => {
  const { on: onChange, emit, reset } = useEventBus<{
    type?: string;
    lnglat: AMap.LngLat;
    address: string;
    overlays: any[];
  }>('change');

  const lnglat = ref();
  const address = ref('');
  const reExec: Fn[] = [];
  var map: AMap.Map | undefined,
    contextMenuPositon: AMap.LngLat,
    placeSearch: any,
    polygonEditor: AMap.PolygonEditor | undefined;
  // polygons = ref<AMap.Polygon[]>([]),
  const updateLnglat = (e) => {
    lnglat.value = e.lnglat
    dispatchChange('lnglat')
  }
  const initEvent = (rightActions) => {
    map!.on('click', (e) => {
      updateLnglat(e)
      closeEditPolygon()
    })
    if (rightActions) {
      var contextMenu = new AMap.ContextMenu();
      rightActions.forEach(({ name, handler }) => {
        contextMenu.addItem(name, function () {
          handler(contextMenuPositon);
          contextMenu.close()
        }, 0);
      })
      map!.on('rightclick', function (e) {
        contextMenu.open(map!, e.lnglat);
        contextMenuPositon = e.lnglat;
      });
    }
  }
  const dispatchChange = (type?: string,): void => {
    emit({
      type,
      overlays: map!.getAllOverlays(),
      lnglat: lnglat.value,
      address: address.value,
    })
  }
  const createMarker = (position: AMap.LngLat, content?: string, draggable?: boolean): AMap.Marker | undefined => {
    if (!map) {
      reExec.push(() => createMarker(position, content, draggable))
      return;
    }
    const opts: AMap.MarkerOptions = {
      position,
      anchor: 'bottom-center'
    }
    // if (content) {
    //     opts.content = `<div class="absolute">
    //     <div class="transform w-28 p-3 -translate-x-1/2 bg-white/60 rounded-lg mb-2 text-sm">${content}</div>
    //     <img src="https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png"/></div>`;
    //     opts.offset = new AMap.Pixel(-20, 0);
    // } else {
    opts.icon = 'https://webapi.amap.com/theme/v1.3/markers/n/mark_b.png'
    // }

    if (draggable) {
      opts.draggable = true;
      opts.cursor = 'move';
    }

    const marker = new AMap.Marker(opts);

    if (draggable) {
      marker.on('dragend', (e) => {
        updateLnglat(e)
        refreshAddress(e.lnglat)
      });
    }
    if (content) {
      marker.setLabel({
        direction: 'top',
        offset: new AMap.Pixel(0, 0),
        content: content,
      });
    }

    map!.add(marker)
    // map!.setFitView();
    map!.setCenter(position);
    return marker;
  }
  const createMarkerCustomContent = (position: AMap.LngLat, content?: string, name?: string): AMap.Marker | undefined => {
    if (!map) {
      reExec.push(() => createMarkerCustomContent(position, content, name))
      return;
    }
    const opts: AMap.MarkerOptions = {
      position: position,
      // 将 html 传给 content
      // content: content,

      // 以 icon 的 [center bottom] 为原点
      offset: new AMap.Pixel(-13, -30)
    }
    if (content) {
      opts.icon = new AMap.Icon({  // 创建 Icon 实例并设置图片 URL
        size: new AMap.Size(40, 50),  // 图标尺寸
        image: content,  // 图片 URL
        imageSize: new AMap.Size(40, 50)  // 图片尺寸
      })
    } else {
      opts.content = '<span></span>';
    }
    const marker = new AMap.Marker(opts);
    if (name) {
      marker.setLabel({
        direction: 'center',
        content: name,
        offset: []
      });
    }
    map!.add(marker)
    // map!.setFitView();
    return marker;
  }
  const clearMarkers = () => {
    clearOverlays('marker')
  }
  const clearPolygon = () => {
    clearOverlays('polygon')
  }
  const clearOverlays = (type?: string) => {
    map && map.getAllOverlays(type).forEach((marker) => marker.remove())
  }

  const createPolygons = (datas) => {
    let polygons = datas.map(opt => {

      const { fillColor = '#1791fc', strokeColor = '#FF33FF', paths = [], extData = {}, events = { onClick: null, rightClick: null }, rightActions } = opt;

      //@ts-ignore
      var polygon = new AMap.Polygon({
        path: paths,
        strokeColor,
        strokeWeight: 6,
        strokeOpacity: 0.2,
        fillOpacity: 0.4,
        fillColor,
        zIndex: 50,
        draggable: false,
        extData
      })
      // events.rightClick && polygon.on('rightclick', events.rightClick)
      if (rightActions) {
        var contextMenu = new AMap.ContextMenu();
        rightActions.forEach(({ name, handler }) => {
          contextMenu.addItem(name, function () {
            handler(polygon);
            contextMenu.close()
          }, 0);
        })
        polygon.on('rightclick', function (e) {
          contextMenu.open(map!, e.lnglat);
          contextMenuPositon = e.lnglat;
        });
      }

      events.onClick && polygon.on('click', events.onClick)
      dispatchChange('createPolygon')
      return polygon;
    })
    map!.add(polygons)
    if (datas.length == 1) {
      map!.setFitView()
    }
  }
  const createPolygon = (opt) => {
    const { fillColor = '#1791fc', strokeColor = '#FF33FF', paths = [], extData = {}, events = { onClick: null, rightClick: null }, rightActions } = opt;

    //@ts-ignore
    var polygon = new AMap.Polygon({
      path: paths,
      strokeColor,
      strokeWeight: 6,
      strokeOpacity: 0.2,
      fillOpacity: 0.4,
      fillColor,
      zIndex: 50,
      extData
    })
    map!.add(polygon)
    // map!.setFitView()

    // events.rightClick && polygon.on('rightclick', events.rightClick)
    if (rightActions) {
      var contextMenu = new AMap.ContextMenu();
      rightActions.forEach(({ name, handler }) => {
        contextMenu.addItem(name, function () {
          handler(polygon);
          contextMenu.close()
        }, 0);
      })
      polygon.on('rightclick', function (e) {
        contextMenu.open(map!, e.lnglat);
        contextMenuPositon = e.lnglat;
      });
    }

    events.onClick && polygon.on('click', events.onClick)
    dispatchChange('createPolygon')
    return polygon;
  }
  const initPolyEditor = (): void => {
    polygonEditor = new AMap.PolygonEditor(map!);
    polygonEditor.on('addnode', () => dispatchChange('polygonEditorAddnode'))
    polygonEditor.on('adjust', () => dispatchChange('polygonEditorAdjust'))
    polygonEditor.on('end', () => dispatchChange('polygonEditorEnd'))
  }

  const initSearch = () => {
    //@ts-ignore
    placeSearch = new AMap.PlaceSearch({
      pageSize: 5, // 单页显示结果条数
      pageIndex: 1, // 页码
      city: '成都',
      citylimit: false,  //是否强制限制在设置的城市内搜索
      map, // 展现结果的地图实例
      panel: "panel", // 结果列表将在此容器中进行展示。
      autoFitView: true // 是否自动调整地图视野使绘制的 Marker点都处于视口的可见范围
    });
    placeSearch.on('listElementClick', (_event) => {
      // console.log(event)
    })
  }
  const refreshAddress = lnglat => new Promise<string>((res, rej) => {
    //@ts-ignore
    var geocoder = new AMap.Geocoder()
    geocoder.getAddress(lnglat, function (status, result) {
      if (status === 'complete' && result.info === 'OK' && result.regeocode) {

        address.value = result.regeocode.formattedAddress
        dispatchChange('refreshAddress')

        res(result.regeocode.formattedAddress)
        return
      }
      rej({ status, result })
    })
  })
  const initEditMarker = () => {
    map!.on('click', (e) => {
      updateLnglat(e);
      refreshAddress(lnglat.value).then(() => {
        clearMarkers()
        createMarker(lnglat.value, undefined, true)
        dispatchChange('createMarkerByClickMap')
      })
    })
  }
  const initAMap = (container: Ref, opt?: any) => new Promise<AMap.Map>((res, rej) => {
    const plugins: string[] = ['AMap.MapType'];
    if (opt.search) {
      plugins.push('AMap.Geocoder', 'AMap.PlaceSearch', 'AMap.AutoComplete')
    }
    if (opt.polygon) {
      plugins.push("AMap.Polygon");
    }
    if (opt.edit == 'polygon') {
      plugins.push('AMap.PolygonEditor', 'AMap.MouseTool')
    }
    // console.log(opt.zoom || 9)
    AMapLoader.load({
      "key": config.appKey,
      "version": "2.0",
      plugins
    }).then(async (amap) => {
      // await tryOnMounted(() => { });
      map = new amap.Map(container.value, {
        labelzIndex: 130,
        // rotateEnable: false,
        // pitchEnable: false,
        zoom: opt.zoom || 9,
        pitch: 10,
        viewMode: '3D',
        zooms: [2, 20],
        animateEnable: false
      }) as AMap.Map;

      if (opt.satellite) {
        map!.add(new AMap.TileLayer.Satellite())
        map!.addControl(new AMap.MapType({
          defaultType: 1,
          position: {
            top: '20px',
            left: '120px',
          }
        }));
      }
      if (!opt.onlyShow) {
        initEvent(opt.rightActions)
      }
      if (opt.edit == 'marker' && !opt.onlyShow) {
        initEditMarker()
      } else if (opt.edit == 'polygon') {
        initPolyEditor()
      }

      reExec.forEach(fn => fn())
      reExec.length = 0;
      res(map!);
    }).catch(rej)
  })
  const destoryMap = () => {
    if (!map) {
      return;
    }
    map.destroy()
    map = undefined;
    polygonEditor = undefined;
    reset()
  }
  const searchMap = (val: string, callback: (address: string) => void) => {
    if (!map) return;
    if (!placeSearch) {
      initSearch()
    }
    placeSearch.search(val, (_status, result) => {
      if (result.info == 'OK') {
        // map.setCenter([
        //   result.poiList.pois[0].location.lng, result.poiList.pois[0].location.lat
        // ])
      } else {
        message.error('未搜索到相关地点，请重新输入');
      }
      if (callback && typeof callback === 'function') {
        callback(result);
      }
    });
  }
  const initAutoComplete = (input: Ref) => {
    //@ts-ignore
    const auto = new AMap.AutoComplete({
      input: input.value
    });
  }
  const searchOverlays = (cb: Fn) => map?.getAllOverlays().find(cb)
  const showOverlay = target => {
    map!.setFitView([target])
  }
  const setOptions = (target: AMap.Polygon, options: AMap.OverlayOptions) => {
    target.setOptions(options);
  }
  const setCenter = (position) => {
    map!.setCenter(position)
  }

  const closeEditPolygon = () => {
    // const target = polygonEditor?.getTarget();
    // target && setOptions(target, {
    //   draggable: false,
    // })
    polygonEditor?.close()
  }
  const editPolygon = (polygon: AMap.Polygon) => {
    // closeEditPolygon()
    // setOptions(polygon, {
    //   draggable: true,
    // })
    // polygon.on('dragend', () => dispatchChange('polygonDragend'))
    polygonEditor!.addAdsorbPolygons([polygon]);
    polygonEditor!.setTarget(polygon);
    polygonEditor!.open();
    map!.setFitView([polygon])
  }

  const getMousetool = () => {
    if (map) {
      const mouseTool = new AMap.MouseTool(map);
      mouseTool.polygon({
        strokeColor: "#FF33FF", //轮廓线颜色
        strokeOpacity: 0.2, //轮廓线透明度
        strokeWeight: 6, //轮廓线宽度
        fillColor: '#1791fc', //多边形填充颜色
        fillOpacity: 0.4, //多边形填充透明度
        strokeStyle: "solid", //线样式还支持 'dashed'
        //strokeDasharray: [30,10], //strokeDasharray 属性在 strokeStyle 是 dashed 时有效
      })
      return mouseTool;
    }
  }

  return { setOptions, closeEditPolygon, clearPolygon, clearOverlays, editPolygon, showOverlay, searchOverlays, initAutoComplete, createPolygon, destoryMap, initAMap, createMarker, searchMap, onChange, clearMarkers, createPolygons, createMarkerCustomContent, setCenter, refreshAddress, getMousetool }
}
